/**	\file		Graph.h
*	\author		Abbas Bazzi
*	\author		Farah Charab
*	\author		Rafah El-Khatib
*	\brief		A header file that constructs the parse tree using Piano.g, the grammar file.
*/

#ifndef _GRAPH_H_
#define _GRAPH_H_
#include <iostream>
#include <map>
#include <cmath>
#include <stdio.h>
#include <sstream>
#include <stdlib.h>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <string>
using namespace std;
 
/**	\class		EDGE
	\brief		Connects two entities or nodes
*/

class EDGE{
public: string source;//!< Parent Node connected to Edge
	string dest;//!< Child Node connected to Edge
	string Fakesource;//!< Modified parent node name, to ensure uniqueness of construction names and maintain the tree structure
	string FakeDest;//!< Modified child node name, to ensure uniqueness of construction names and maintain the tree structure
	string weight;//!< Indicates the property of the edge concerning direction, when it matters. That is, sometimes in mathematical statements, it matters whether a child is a right child or a left child, such as cases of assignment and inequalities. Thus, this string either takes the value "right" or "left".
	EDGE(string source1, string dest1, string weight1,string Fake1, string Fake2);
};
 
/**    \class    NODE
       \brief    Consists of one entity, whose type (variable/constant/operator), data content, and temporary name (to ensure uniqueness of different instances of an entity) are specified using explicit members of the class. A class member also contains a vector of adjacent edges.
*/

class NODE{
public: string type;//!< Either Variable, Constant, or Operator.
	string data;//!< Content of Node.
	string Fake;//!< Mapped name or content, to ensure uniqueness of construction names and maintain the tree structure.
	NODE(string data1, string type1,string Fake1);
	vector<EDGE> adjEdges;//!< Each node has a vector of edges which consists of the edges connected to it.
/**	\brief		Function that prints the contents of adjEdges. That is, it prints the name of the node then lists all the edges it has.
*/
	void print();
};

/**	\typedef	MapFromStringToInt
*	\param		A string to index the map.
*	\brief		Map from string to integer, where the integer will represent a certain index.
*/
typedef map <string, int> MapFromStringtoInt;
/**	\typedef	MapFromInttoString
*	\param		An integer to index the map.
*	\brief		Map from integer to string.
*/
typedef map <int , string> MapFromInttoString;
/**	\typedef	MapFromStringToString
*	\param		A string to index the map.
*	\brief		Map from string to string.
*/
typedef map <string, string> MapFromStringtoString;
/**	\typedef	AdjacencyList
*	\param		A vector of strings.
*	\brief		A vector of vectors, where the inner vectors contain strings. It is an adjacency list, implemented as a vector of vectors. It represents the graph: Each node and the corresponding adjacent nodes
*/
typedef vector < vector < string > > AdjacencyList;
/**	\typedef	TypeOfNodes
*	\param		A string to index the map.
*	\brief		Map from a string to a pair consisting of an integer and a string.
*/
typedef map <string, pair <int, string > > TypeOfNodes;
/**	\typedef	vectorNodes
*	\param		Member of type NODE.
*	\brief		A vector of nodes of type NODE.
*/
typedef vector <NODE> vectorNodes;
/**	\typedef	vectorEdges
*	\param		Member of type EDGE.
*	\brief		A vector of edges of type EDGE.
*/
typedef vector <EDGE> vectorEdges;

/**
*	\class		__NOT
*	\brief		This is the class of our constructed graph. It contains several maps that will correlate between nodes and indices, names and temporary names (used to avoid duplicate confusion when the same entity is called several times), and nodes and their types.
*/
class __NOT {
public:
	int MAXnumb; //!< Represents the maximum allowed number of colors that the computer may hold. It has a constant value of 10^8.
	AdjacencyList adjlistout;//!< Adjacency list used to represented our graph.
	TypeOfNodes nodeType;//!< Map from a string to a pair consisting of an integer and a string. The passed string represents the inputted value of the Node. It is mapped first to an integer which corresponds to the type of the node, which may be a variable, constant, or, operator. Second, it is mapped to a string which corresponds to the mapped name of the node. This modified name is demonstrated on the graph.
	MapFromStringtoString dependencies;//!< Map that keeps track of the last updated variable. Since we do not allow the repetition of edge association to the same root node, each variable with a repeated name has a modified name consisting of the initial name and an appended index. This map stores the latest such modified variable.
	MapFromStringtoInt countt;//!< Map that keeps track of the number of times a variable/operator appears in a program.
	map <int,int> takenCol;//!< Map that keeps track of the colors used so far in the input program's graph.
	MapFromStringtoInt adjplace;//!< Map that maps each string to an integer value, so that accessing the adjacency list would be more efficient.
	MapFromStringtoInt fakecol;//!< This is a map that maps each instance of a node to a certain color.
	MapFromInttoString adjplacee;//!< Map that maps an integer value to a string. The integer would represent a Node according to the construction we made on the map "adjplace", and so this map "adjplacee" would return the node's type:operator,constant, or variable.
	char * tempSetRel; //!< This is temporary variable to keep track of the root of each subtree when setting the relation between sets in Antlr. That is, in Antlr, one expression can use several others. As it goes deeper into dependencies, we must have a temporary variable that keeps track of the previous root. This one is used in case the sub-parental tree consists of a Set Expression.
	char * tempMulRel;//!< This is temporary variable to keep track of the  root of each subtree when setting the relation between multiplicative/division operations in  Antlr. The logic is similar to that described in tempSetRel explanation.
	char * tempAddRel; //!< This is temporary variable to keep track of the  root of each subtree when setting the relation between additive/subtractive operations in  Antlr. The logic is similar to that described in the tempSetRel explanation.
	char * tempAndNotRel;//!< This is temporary variable to keep track of the  root of each subtree when setting the relation between logical operations in  Antlr. The logic is similar to that described in the tempSetRel explanation.
	char * natAssig;//!< This is temporary variable to keep track of the  root of each subtree when using the assignment operation in  Antlr. The logic is similar to that described in the tempSetRel explanation.	
	MapFromInttoString Type;//!< Map that will be used in this file as a constant-valued map. It is used to indicate the type of a variable. The indices of the map ranging from zero to 4 take the respetive types: natural number, real number, set, map, and tuple.
	MapFromStringtoString VartoType;//!< Map that takes a variable name and detects its type; that is, whether it is a natural number, real number, set, map, or tuple.
	MapFromStringtoString FakeOf;//!< Map that takes a string that represents a variable's name and returns the modified name of this variable that is used to ensure the uniqueness of the variable names and maintain the tree structure.
	vectorNodes Nodes;//!< Vector of nodes; members of class NODE.
	vectorEdges Edges;//!< Vector of edges; members of class EDGE.
	MapFromStringtoInt NodeToIndex;//!< Map that takes a node name and returns its index in the graph (adjacency list "adjplace").
	MapFromStringtoInt AlreadyCreated;//!< Map that takes a node name and returns 1 if it has already been created.
	int numbOfNodes;//!< Counter that keeps track of how many nodes have been created in the program so far.
	int isNot; //!<	This variable is used to indicate whether an optional statement in antlr is used or not.
	
/**	\brief		Print Function that outputs all edges found in the vector of edges "Edges", along with their weights
*/
	void printEdges(){for (int i=0;i<Edges.size();i++) cout<<Edges[i].source<<" to "<<Edges[i].dest<<" with "<<Edges[i].weight<<endl;};
/**	\brief		Print Function that outputs all nodes in the vector of nodes "Nodes" according to the print function described in the Node class.
*/
	void printNodes(){for (int i=0;i<Nodes.size();i++) Nodes[i].print();};

/**
*	\brief		Function that takes an integer and returns a string indicating the corresponding type. It the integer is 0, the type is a variable. If 1, it is a constant. If 2, it is an operator.
	\param		i An integer that indicates the type 
*	\return		Node type in string form
*/
	string getType(int i);

/**
*	\brief		Constructor of our graph that initializes the map Type as described earlier, sets the constant MAXnumb to its predetermined value, 10^8, and initializes the number of nodes to zero.
*/
        __NOT ();
/**
*	\brief		Print Function that outputs the graph.
*/
	void print();
/**
*	\param		s string indicating type of variable
*	\brief		Given the type of the variable in string form, the function returns a predefined integer
*	\return		indicator of variable type in integer form 
*/
	int getNumber(string s);

/**
*	\param		i An integer indicating the frequency of a certain variable's occurrence
*	\brief		Given an integer indicating the frequency of a certain variable's occurrence, the function returns a modified version of the variable's name, which is the name itself appended by the passed integer
*	\return		Modified variable name in string form
*/
	string headName(int i);
/**
*	\param		i An integer that represents a node
*	\brief		Given an integer which indexes the adjacency list "adjplacee" to represent a node, the function finds its type and updates all appropriate members of the graph, such as the total number of nodes, the fact that this variable is not creates, the Nodes vector, etc.
*	\return		indicator of variable type in string form 
*/
	string FillI(int i);

/**
*	\param		i An integer that serves as the first-dimension index to our graph, represented in an adjacency list
*	\param		j An integer that serves as the second-dimension index to our graph, represented in an adjacency list
*       \brief    Given a pair of integers, i and j, which index the adjacency list "adjlistout" to represent a node, the function finds its original name (before modification by indexing) and updates all appropriate members of the graph, such as the total number of nodes, the fact that this variable is not creates, the Nodes vector, etc.
*	\return		original variable name in string form 
*/
	string FillIJ(int i, int j);
/**
*	\brief		Function that traverses the adjacency list generated during parsing the grammar file, Piano.g, and constructs a graph.
*/
	void Construct();
/**
*	\param		a A string that represents a variable or operator
*	\brief		Function that checks whether or not the passed string has already been declared as a variable or operator. If it has not, the string is added to the adjacency list as a node and the appropriate members of the graph are updated.
*/
	void checkandadd(string a);

/**     
*	\param		m A string that represents a variable or operator
*	\brief		Given a string, the function appends its count; that is, the number of times it has been declared so far. It then creates a node in the map nodeType where the string is concatenated to the count and mapped to a pair (2,l) where 2 indicates that the string is an operator and l is the original name of the operator passed to the function.
*	\return		Modified name (original with appended count) in string form
*/
	string getname(string m);
/**  
*	\param		m A string that represents a variable or operator
*	\brief		Given a string, the function appends its count; that is, the number of times it has been declared so far. It then returns the string that is concatenated to the count.
*	\return		Modified name (original with appended count) in string form
*/
	string getTempname(string m);

/**
*	\param		m A string that represents a variable or an operator
*	\brief		Given a string, the function appends its count; that is, the number of times it has been declared so far. It then creates a node in the map nodeType where the string is concatenated to the count and mapped to a pair (0,l) where 0 indicates that the string is a variable and l is the original name of the variable passed to the function.
*	\return		Modified name (original with appended count) in string form
*/
	 string getnameVar(string m);
/**
*	\param		m A string representing the name of a node
*	\param		i An integer indicating the type of the node
*	\brief		Given a string and an integer, the function creates a node in the map nodeType where the string is mapped to a pair (i,l), where i is the passed integer, and indicates the type of the node (variable/constant/operator), and l is the passed string.
*/
	void setType(string m, int i);
/**
*	\param		oper A string that holds the name of the parent node in the subtree created by the three passed parameters of this function.
*	\param		opera1 A string that holds the name of the first child node in the subtree created by the three passed parameters of this function.
*	\param		opera2 A string that holds the name of the second child node in the subtree created by the three passed parameters of this function.
*	\brief		Given three strings a,b, and c, the function creates a subtree in our parse tree, where a is the parent node and b and c are its children nodes.
*	\return		Name of parent node
*/
	char* RootReturn(string oper, string opera1, string opera2);
/**
*	\param		oper1 A string that holds the name of the first operand in the assignment subtree created by the three passed parameters of this function. It receives the assigned value.
*	\param		assig A string that holds the value ":=". It is the assignment operator.
*	\param		oper2 A string that holds the name of the second operand in the assignment asubtree created by the three passed parameters of this function. It gives the assigned value.
*	\brief		Given three strings a,b, and c, the function creates a subtree in our parse tree, where a is the parent with only one child: b, and b is the parent node of one child: c. This function is used for assignments, since the assignment operator ":=" receives a value and returns one.
*	\return		Name of assignment operator in character array form.
*/
char * CreateAssignment(string oper1, string assig, string oper2);

/**
*	\param		oper A string that holds the name of the source node in the edge to be created.
*	\param		opera A string that holds the name of the destination node in the edge to be created.
*	\brief		Given two strings, the function creates an edge pointing from the first one to the second.
*	\return		Name of first operand in character array form
*/
	char * CardinAssig (string oper, string opera);

};
#endif
